package com.zsk.shop.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.domain.Shop;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zsk.shop.api.apple.UserInfoApple;
import com.zsk.shop.api.idcard.AliYunTrueNameCheck;
import com.zsk.shop.common.base.BaseResponse;
import com.zsk.shop.common.base.BizException;
import com.zsk.shop.common.base.NoMsgException;
import com.zsk.shop.common.base.model.token.UserSimple;
import com.zsk.shop.common.base.page.BasePageFactory;
import com.zsk.shop.common.base.page.BasePageParams;
import com.zsk.shop.common.constant.Constant;
import com.zsk.shop.common.enums.EnumQRCodeType;
import com.zsk.shop.common.socket.ServicePushSocketServer;
import com.zsk.shop.common.utils.*;
import com.zsk.shop.entity.ShopGoods;
import com.zsk.shop.entity.ShopOrder;
import com.zsk.shop.entity.ShopUser;
import com.zsk.shop.entity.UserLogInfo;
import com.zsk.shop.entity.yulink.YlUser;
import com.zsk.shop.enums.*;
import com.zsk.shop.mapper.ShopUserMapper;
import com.zsk.shop.model.params.*;
import com.zsk.shop.model.results.*;
import com.zsk.shop.model.wechatDecode.AppUserWXParam;
import com.zsk.shop.service.yulink.YlUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Ys
 * @date 2022年02月09日 16:40
 */
@Service
public class ShopUserService extends ServiceImpl<ShopUserMapper, ShopUser> {

    private static final Logger logger = LoggerFactory.getLogger(ShopUserService.class);

    @Resource
    private TokenUtil tokenUtil;
    @Resource
    private VerificationCodeService verificationCodeService;
    @Resource
    private ServicePushSocketServer servicePushSocketServer;
    @Resource
    private UserLogInfoService userLogInfoService;
    @Resource
    private YlUserService ylUserService;
    @Resource
    private UserAccountService userAccountService;
    @Resource
    private ShopOrderPointsService shopOrderPointsService;
    @Resource
    private ShopOrderService shopOrderService;
    @Resource
    private BaseService baseService;
    @Autowired
    private AliYunTrueNameCheck aliYunTrueNameCheck;
    @Resource
    private WxDecodeService wxDecodeService;
    @Resource
    private DataDictionaryService dataDictionaryService;

    @Transactional(rollbackFor = {Exception.class, BizException.class})
    public BaseResponse<LoginInfoResult> login(ShopUserLoginParams params) {
        LoginInfoResult loginInfoResult = new LoginInfoResult();
        String loginType = params.getLoginType();
        String pwdLogin = EnumUserLoginType.PWD_LOGIN.getCode();
        String smsLogin = EnumUserLoginType.SMS_LOGIN.getCode();
        String touristLogin = EnumUserLoginType.TOURIST_LOGIN.getCode();
        if (ToolUtil.isEmpty(loginType)) {
            return BaseResponse.error("系统错误，当前登录类型不正确");
        } else {
            if (!loginType.equals(touristLogin)) {
                String phone = params.getPhone();
                if (ToolUtil.isEmpty(phone)) {
                    return BaseResponse.error("当前手机号为空");
                } else {
                    if (RegexCheckUtils.isNotMobile(phone)) {
                        return BaseResponse.error("请填写正确格式的手机号码");
                    }
                }
            }
        }
        loginInfoResult.setHavePhone(false);
        loginInfoResult.setBingWechat(false);
        loginInfoResult.setBingJsWechat(false);
        loginInfoResult.setBingMiniWechat(false);
        loginInfoResult.setHaveIdCard(false);
        loginInfoResult.setHavePwd(false);
        loginInfoResult.setToken("");
        loginInfoResult.setMsg("");
        if (loginType.equals(pwdLogin)) {
            Integer checkCode = this.checkPwd(params);
            loginInfoResult.setPwdType(checkCode);
            loginInfoResult.setMsg(EnumCheckPwd.getNameByCode(checkCode));
            if (checkCode.equals(EnumCheckPwd.YES.getCode())) {
                loginInfoResult = this.loginUser(loginInfoResult, params.getPhone());
                return BaseResponse.success(loginInfoResult);
            }
        } else if (loginType.equals(smsLogin)) {
            Integer checkCode = this.checkCode(params);
            loginInfoResult.setSmsType(checkCode);
            loginInfoResult.setMsg(EnumCheckCode.getNameByCode(checkCode));
            if (checkCode.equals(EnumCheckCode.YES.getCode())) {
                loginInfoResult = this.loginUser(loginInfoResult, params.getPhone());
                return BaseResponse.success(loginInfoResult);
            }
        }
        return BaseResponse.success(loginInfoResult);
    }

    public synchronized BaseResponse<LoginInfoResult> reg(ShopUserRegParams params, String pwd) {
        //校验手机号是否被注册
        ShopUser user = this.queryTrueUserByPhone(params.getPhone());
        if (ToolUtil.isNotEmpty(user)) {
            return BaseResponse.error("当前手机账号已注册");
        }
        //校验验证码
        if (!verificationCodeService.checkCode(params.getPhone(), EnumVerificationType.REG.getCode(), params.getCode())) {
            return BaseResponse.error("验证码校验失败");
        }
        //当前账号不是会员的话不让使用
        String parentInviteCode = params.getInviteCode();
        ShopUser parentUser = new ShopUser();
        if (ToolUtil.isNotEmpty(parentInviteCode)) {
            parentUser = this.queryByInviteCode(parentInviteCode);
            if (ToolUtil.isNotEmpty(parentUser)) {
                if (parentUser.getVipLevel() < 1) {
                    return BaseResponse.error("当前邀请码未激活。");
                }
            } else {
                return BaseResponse.error("当前邀请码无效，请填写有效值。");
            }
        }
        YlUser ylUser = ylUserService.queryTrueUserByPhone(params.getPhone());
        String userNo = RedisUtil.getServiceKeyHaveDateByType(ServiceKeyTypeEnum.USER.getValue());
        String avatar = Constant.getDefaultAvatar();
        String name = "Shop" + params.getPhone().substring(7, 11);
        if (ToolUtil.isNotEmpty(ylUser)) {
            userNo = ylUser.getUserNo();
            avatar = ylUser.getAvatar();
            name = ylUser.getName();
        } else {
            ylUserService.addUser(params.getPhone(), avatar, name, userNo);
        }
        //生成用户 返回token直接登录
        String parentUserNo = parentUser.getUserNo();
        Date time = new Date();
        String inviteCode = getNewTgm();
        user = ShopUser.builder().userNo(userNo).nickName(name).phone(params.getPhone()).password(ToolUtil.isEmpty(pwd) ? "" : pwd)
                .avatar(avatar).sex(EnumGenderType.UN_KNOW.getCode()).inviteCode(inviteCode).parentUserNo(parentUserNo)
                .subUserId("").lv(1).wxNickName("").wxAvatar("").wxOpenId("").wxMiniOpenId("").wxUnionId("")
                .trueName("").identityCard("")
                .isDeleted(false).isInvalid(false).createTime(time)
                .build();
        this.save(user);
        //自己写入上级的下级
        if (ToolUtil.isNotEmpty(params.getInviteCode()) && !parentUser.getUserNo().equals("US0001")) {
            insertParentSubUserId(parentUser, user, false);
        }
        LoginInfoResult loginInfoResult = new LoginInfoResult();
        loginInfoResult.setToken("");
        loginInfoResult.setMsg("");
        loginInfoResult = this.loginUser(loginInfoResult, params.getPhone());
//        checkLv(inviteCode, null, true);
        return BaseResponse.success(loginInfoResult);
    }

    /**
     * 找到上级把下级数据填入
     *
     * @param parentUser 上级
     * @param subUser    本级
     */
    private void insertParentSubUserId(ShopUser parentUser, ShopUser subUser, Boolean isCycle) {
        if (!parentUser.getUserNo().equals("US0001")) {
            if (isCycle) {
                parentUser.setSubUserId(parentUser.getSubUserId() + "," + subUser.getSubUserId());
            } else {
                parentUser.setSubUserId(parentUser.getSubUserId() + "," + subUser.getId());
            }
            //优化长度
            String subUserIds = parentUser.getSubUserId();
            List<String> all = Arrays.asList(subUserIds.split(","));
            List<String> subUserIdList = all.stream().filter(x -> ToolUtil.isNotEmpty(x)).distinct().collect(Collectors.toList());
            parentUser.setSubUserId(EntityConvertUtils.listToString(subUserIdList));
            this.saveOrUpdate(parentUser);
            ShopUser subNewUser = EntityConvertUtils.convertAToB(parentUser, ShopUser.class);
            parentUser = this.queryByUserNo(subNewUser.getParentUserNo());
            if (ToolUtil.isNotEmpty(parentUser) && ToolUtil.isNotEmpty(parentUser.getParentUserNo())) {
                insertParentSubUserId(parentUser, subNewUser, true);
            } else {
                return;
            }
        } else {
            return;
        }
    }

    /**
     * 修改用户信息
     *
     * @param params
     * @return
     */
    public BaseResponse editUser(EditUserParams params) {
        LambdaUpdateWrapper<ShopUser> updateWrapper = new LambdaUpdateWrapper<>();
        Boolean shouldChangeERCode = false;
        if (ToolUtil.isNotEmpty(params)) {
            if (ToolUtil.isNotEmpty(params.getAvatar())) {
                shouldChangeERCode = true;
                updateWrapper.set(ShopUser::getAvatar, params.getAvatar());
            } else if (ToolUtil.isNotEmpty(params.getNickName())) {
                updateWrapper.set(ShopUser::getNickName, params.getNickName());
            } else if (ToolUtil.isNotEmpty(params.getSex())) {
                updateWrapper.set(ShopUser::getSex, params.getSex());
            }
            updateWrapper.eq(ShopUser::getUserNo, HttpContext.getUserNo());
            this.update(updateWrapper);
        }
        if (shouldChangeERCode) {
            ShopUser shopUser = this.queryByUserNo(HttpContext.getUserNo());
            //修改二维码头像
            ImageUtil.greatQRCodeImg(getContent(shopUser.getNickName(), shopUser.getUserNo(), shopUser.getInviteCode())
                    , shopUser.getInviteCode(), shopUser.getAvatar(), EnumQRCodeType.ONE.getCode());
        }
        return BaseResponse.success();
    }

    public static String getContent(String name, String userNo, String inviteCode) {
        QRInfoParam param = new QRInfoParam();
        param.setUserNo(userNo);
        param.setName(name);
        param.setType(EnumQRCodeType.ONE.getCode());
        param.setInviteCode(inviteCode);
        return JSON.toJSONString(param);
    }

    private ShopUser queryByInviteCode(String inviteCode) {
        if (ToolUtil.isEmpty(inviteCode)) {
            return null;
        }
        LambdaQueryWrapper<ShopUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShopUser::getInviteCode, inviteCode);
        queryWrapper.last("limit 1");
        return getOne(queryWrapper);
    }

    /**
     * 通过手机号查询账号后，返回授权登录信息
     *
     * @param loginInfoResult 已有登录内容
     * @param phone           手机号
     * @return 登录返回实体
     */
    public LoginInfoResult loginUser(LoginInfoResult loginInfoResult, String phone) {
        //生成用户登录信息，只允许单点登录
        ShopUser user = this.queryTrueUserByPhone(phone);
        //查询用户之前的登录状态，如果已登录之前的掉线
        servicePushSocketServer.clearUserInfoByUserNo(user.getId(), user.getUserNo(), 1, false);
        userLogInfoService.insertInfo(user.getUserNo(), EnumLoginPlatform.getNameByCode(HttpContext.getPlatform()),
                HttpContext.getDeviceToken(), EnumUserLogType.LOGIN.getCode());
        UserSimple userSimple = EntityConvertUtils.convertAToB(user, UserSimple.class);
        loginInfoResult.setToken(tokenUtil.genToken(userSimple, null));
        loginInfoResult.setHavePwd(ToolUtil.isNotEmpty(user.getPassword()));
        loginInfoResult.setHavePhone(ToolUtil.isNotEmpty(user.getPhone()));
        loginInfoResult.setBingWechat(ToolUtil.isNotEmpty(user.getWxUnionId()));
        loginInfoResult.setBingJsWechat((ToolUtil.isNotEmpty(user.getWxJsOpenId())));
        loginInfoResult.setBingMiniWechat(ToolUtil.isNotEmpty(user.getWxMiniOpenId()));
        loginInfoResult.setHaveIdCard(ToolUtil.isNotEmpty(user.getTrueName()) ? true : false);
        LoginUserResult loginUserResult = EntityConvertUtils.convertAToB(user, LoginUserResult.class);
        loginInfoResult.setUserResult(loginUserResult);
        return loginInfoResult;
    }

    /**
     * @param params 登录参数
     * @return {@link EnumCheckPwd}
     */
    private Integer checkPwd(ShopUserLoginParams params) {
        ShopUser user = queryTrueUserByPhoneNoLogOut(params.getPhone());
        if (ToolUtil.isEmpty(user)) {
            throw new NoMsgException(EnumCheckPwd.NULL_PHONE.getName());
        }
        //判定是否注销
        if (user.getIsDeleted()) {
            throw new NoMsgException(EnumCheckPwd.LOG_OUT_ACCOUNT.getName());
        }
        if (ToolUtil.isEmpty(user.getPassword())) {
            throw new NoMsgException(EnumCheckPwd.PWD_NULL.getName());
//                return EnumCheckPwd.PWD_NULL.getCode();
        } else {
            if (ToolUtil.isEmpty(params.getPwd())) {
                throw new NoMsgException(EnumCheckPwd.PWD_ERROR.getName());
            }
            if (user.getPassword().equals(params.getPwd())) {
                return EnumCheckPwd.YES.getCode();
            } else {
                throw new NoMsgException(EnumCheckPwd.PWD_ERROR.getName());
            }
        }
    }

    /**
     * @param params 登录参数
     * @return {@link EnumCheckCode}
     */
    private Integer checkCode(ShopUserLoginParams params) {
        ShopUser user = queryTrueUserByPhoneNoLogOut(params.getPhone());
        if (ToolUtil.isEmpty(user)) {
            //当前注册登录统一，使空账号形成账号
            user = createUser(params.getPhone());
            //生成二维码头像
            ImageUtil.greatQRCodeImg(ShopUserService.getContent(user.getNickName(), user.getUserNo(), user.getInviteCode())
                    , user.getInviteCode(), user.getAvatar(), EnumQRCodeType.ONE.getCode());
//            throw new NoMsgException(EnumCheckPwd.NULL_PHONE.getName());
        }
        //获取验证码校验
        Boolean isTrue = verificationCodeService.checkCode(params.getPhone(), EnumVerificationType.LOGIN.getCode(), params.getCode());
        //判定是否注销
        if (user.getIsDeleted()) {
            throw new NoMsgException(EnumCheckPwd.LOG_OUT_ACCOUNT.getName());
        }
        if (isTrue) {
            return EnumCheckCode.YES.getCode();
        } else {
            throw new NoMsgException(EnumCheckCode.CODE_ERROR.getName());
        }
    }

    public ShopUser createUser(String phone) {
        //生成用户 返回token直接登录
        String inviteCode = getNewTgm();
        String avatar = Constant.getDefaultAvatar();
        String userNo = RedisUtil.getServiceKeyHaveDateByType(ServiceKeyTypeEnum.USER.getValue());
        String name = "Shop" + phone.substring(7, 11);
        ShopUser user = ShopUser.builder().userNo(userNo).nickName(name).phone(phone).password("")
                .avatar(avatar).sex(EnumGenderType.UN_KNOW.getCode()).isInvalid(false).subUserId("").lv(1)
                .isDeleted(false).createTime(new Date()).inviteCode(inviteCode).build();
        this.save(user);
        return user;
    }

    public ShopUser queryTrueUserByPhoneNoLogOut(String phone) {
        LambdaQueryWrapper<ShopUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShopUser::getPhone, phone);
        queryWrapper.eq(ShopUser::getIsDeleted, false);
        queryWrapper.orderByAsc(ShopUser::getIsDeleted);
        queryWrapper.last("limit 1");
        return this.getOne(queryWrapper);
    }

    public ShopUser queryTrueUserByPhone(String phone) {
        LambdaQueryWrapper<ShopUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShopUser::getPhone, phone);
        queryWrapper.eq(ShopUser::getIsDeleted, false);
        queryWrapper.last("limit 1");
        return this.getOne(queryWrapper);
    }

    public String getNewTgm() {
        String tgm = randomTgm();
        while (true) {
            if (queryTgmExist(tgm)) {
                tgm = randomTgm();
                continue;
            } else {
                break;
            }
        }
        if (tgm.length() <= 6) {
            String initStr = "000000";
            String zoreStr = initStr.substring(tgm.length(), 6);
            tgm = zoreStr + tgm;
        }
        return tgm;
    }

    private Boolean queryTgmExist(String tgm) {
        LambdaQueryWrapper<ShopUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShopUser::getInviteCode, tgm);
        queryWrapper.last("limit 1");
        ShopUser shopUser = this.getOne(queryWrapper);
        return ToolUtil.isNotEmpty(shopUser) ? true : false;
    }

    private String randomTgm() {
        Integer tgmInt = new Random().nextInt(999999);
        String tgm = tgmInt.toString();
        return tgm;
    }

    public BaseResponse<MineInviteUserInfoResult> mineInviteUserList(BasePageParams params) {
        MineInviteUserInfoResult infoResult = new MineInviteUserInfoResult();
        Page pageContext = BasePageFactory.defaultPage(params.getPage(), params.getLimit());
        LambdaQueryWrapper<ShopUser> queryWrapper = new LambdaQueryWrapper<>();
        String userNo = HttpContext.getUserNo();
        ShopUser shopUser = this.queryByUserNo(userNo);
        queryWrapper.eq(ShopUser::getParentUserNo, userNo);
        queryWrapper.eq(ShopUser::getIsDeleted, false);
        queryWrapper.eq(ShopUser::getIsInvalid, false);
        IPage page = this.page(pageContext, queryWrapper);
        List<MineInviteUserListResult> results = EntityConvertUtils.convertAListToBList(page.getRecords(), MineInviteUserListResult.class);
        for (MineInviteUserListResult result : results) {
            result.setPhone(EntityConvertUtils.handlePhone(result.getPhone()));
        }
        infoResult.setIsVip(shopUser.getVipLevel() > 0 ? true : false);
        infoResult.setQrCode(Constant.QRCODE_IMG_URL_PROD.replace("INVATECODE", shopUser.getInviteCode()));
        infoResult.setInvitedCode(infoResult.getIsVip() ? shopUser.getInviteCode() : "");
        infoResult.setHaveParent(ToolUtil.isNotEmpty(shopUser.getParentUserNo()) ? true : false);
        infoResult.setTeamCount(teamCount(userNo));
        infoResult.setList(results);
        infoResult.setInviteCount(page.getTotal());
        if (ToolUtil.isNotEmpty(shopUser.getSubCompany())) {
            infoResult.setSubCompanyName(shopUser.getSubCompany());
        } else {
            String subComgpanyName = getSubCompanyName(shopUser.getId());
            infoResult.setSubCompanyName(subComgpanyName);
        }
        List<ShopUser> subShopUserList = this.subShopUserByParentUserNo(userNo);
        infoResult.setInviteLv5Count(subShopUserList.stream().filter(
                x -> x.getLv().equals(EnumRatioWithLv.TOP.getLv())).collect(Collectors.toList()).size());
        return BaseResponse.success("返回团队礼包统计", infoResult, Integer.parseInt(page.getTotal() + ""));
    }

    public List<ShopUser> subShopUserByParentUserNo(String userNo) {
        LambdaQueryWrapper<ShopUser> queryWrapper = new LambdaQueryWrapper<>();
        ShopUser shopUser = this.queryByUserNo(userNo);
        queryWrapper.eq(ShopUser::getParentUserNo, userNo);
        queryWrapper.eq(ShopUser::getIsDeleted, false);
        queryWrapper.eq(ShopUser::getIsInvalid, false);
        return list(queryWrapper);
    }

    private String getSubCompanyName(Long id) {
        LambdaQueryWrapper<ShopUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(ShopUser::getSubUserId, id.toString());
        queryWrapper.ne(ShopUser::getSubCompany, "");
        List<ShopUser> shopUserList = list(queryWrapper);
        String name = "";
        for (ShopUser shopUser : shopUserList) {
            String subUserIds = shopUser.getSubUserId();
            List<String> all = Arrays.asList(subUserIds.split(","));
            if (ToolUtil.isNotEmpty(all) && all.contains(id.toString())) {
                name = shopUser.getSubCompany();
                break;
            }
        }
        return name;
    }

//    public BaseResponse updatePwd(ShopUserUpdatePwdParams params) {
//        String updateType = params.getUpdateType();
//        String pwd = EnumUserUpdatePwdType.PWD.getCode();
//        String sms = EnumUserUpdatePwdType.SMS.getCode();
//        if (ToolUtil.isEmpty(updateType)) {
//            return BaseResponse.error("系统错误，当前类型不正确");
//        }
//        ShopUser user = this.queryByUserNo(HttpContext.getUserNo());
//        if (ToolUtil.isEmpty(user)) {
//            throw new NoMsgException(EnumCheckPwd.NULL_PHONE.getName());
//        }
//        if (updateType.equals(pwd)) {
//            if (!user.getPassword().equals(params.getPwdOld())) {
//                return BaseResponse.error("旧密码校验错误");
//            }
//        } else if (updateType.equals(sms)) {
//            Boolean isTrue = verificationCodeService.checkCode(user.getPhone(), EnumVerificationType.CHANGE_PWD.getCode(), params.getCode());
//            if (!isTrue) {
//                return BaseResponse.error("验证码校验错误");
//            }
//        }
//        user.setPassword(params.getPwdNew());
//        this.saveOrUpdate(user);
//        return BaseResponse.success("修改密码成功");
//    }

    public ShopUser queryByUserNo(String userNo) {
        if (ToolUtil.isEmpty(userNo)) {
            return null;
        }
        LambdaQueryWrapper<ShopUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShopUser::getUserNo, userNo);
        queryWrapper.last("limit 1");
        return getOne(queryWrapper);
    }

    public ShopUser queryByPhone(String phone) {
        LambdaQueryWrapper<ShopUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShopUser::getPhone, phone);
        queryWrapper.last("limit 1");
        return getOne(queryWrapper);
    }

    public synchronized BaseResponse certification(IdentityCertificationUserParams params) {
        ShopUser user = this.queryTrueInfo(params.getName(), params.getIdCard());
        if (ToolUtil.isNotEmpty(user)) {
            return BaseResponse.error("该身份信息已绑定实名过账号。");
        }
        String userNo = HttpContext.getUserNo();
        ShopUser userInfo = this.queryByUserNo(userNo);
        if (ToolUtil.isNotEmpty(userInfo) && ToolUtil.isNotEmpty(userInfo.getTrueName()) && ToolUtil.isNotEmpty(userInfo.getIdentityCard())) {
            return BaseResponse.error("请勿重复提交实名认证信息，如有问题请咨询客服。");
        }
        if (ToolUtil.isNotEmpty(params)) {
            //过滤校验身份证号码是否合法
            if (!IdentityDocumentUtil.validateCard(params.getIdCard())) {
                return BaseResponse.error("非法身份证号");
            }
            Boolean result = aliYunTrueNameCheck.check(params.getIdCard(), params.getName());
            if (result) {
                userInfo.setIdentityCard(params.getIdCard());
                userInfo.setTrueName(params.getName());
                this.updateById(userInfo);
                return BaseResponse.success();
            } else {
                return BaseResponse.error("姓名和身份证号不一致");
            }
        }
        return BaseResponse.error("参数错误");
    }

    private ShopUser queryTrueInfo(String name, String idCard) {
        LambdaQueryWrapper<ShopUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShopUser::getTrueName, name);
        queryWrapper.eq(ShopUser::getIdentityCard, idCard);
        queryWrapper.eq(ShopUser::getIsDeleted, false);
        queryWrapper.last("limit 1");
        return getOne(queryWrapper);
    }

    public BaseResponse<ShopUserCenterInfoResult> centerInfo(Boolean isPc) {
        String userNo = HttpContext.getUserNo();
//        String userNo = "US2020123114120202";
        ShopUser user = this.queryByUserNo(userNo);
        if (ToolUtil.isEmpty(user)) {
//            throw new BizException(BizExceptionEnum.TOKEN_EXPIRED.getCode(), BizExceptionEnum.TOKEN_EXPIRED.getMessage());
            return BaseResponse.error("当前用户有误");
        }
        ShopUserCenterInfoResult result = EntityConvertUtils.convertAToB(user, ShopUserCenterInfoResult.class);
        String trueName = user.getTrueName();
        result.setTrueName(trueName);
        result.setHavePwd(ToolUtil.isNotEmpty(user.getPassword()) ? true : false);
        result.setHaveIdCard(ToolUtil.isNotEmpty(trueName) ? true : false);
        result.setHaveWx(ToolUtil.isNotEmpty(user.getWxUnionId()));
        result.setHaveInviteUser(ToolUtil.isNotEmpty(user.getParentUserNo()));
        result.setUserBalance(userAccountService.getUserMoneyAccountNowBalance(userNo)
                .setScale(2, BigDecimal.ROUND_HALF_UP).toString());
        result.setUserPoint(shopOrderPointsService.getTotalPoint(userNo, null).toString());
        result.setSexStr(EnumGenderType.getNameByCode(user.getSex()));
        result.setIsVip(result.getVipLevel() > 0 ? true : false);
        result.setQrCode(Constant.QRCODE_IMG_URL_PROD.replace("INVATECODE", result.getInviteCode()));
        result.setInviteCode(result.getIsVip() ? result.getInviteCode() : "");
        result.setWxnNickName(user.getWxNickName());
        result.setWxAvatar(user.getWxAvatar());
        return BaseResponse.success(result);
    }

    public BaseResponse updatePwdNew(String pwdNew) {
        ShopUser user = this.queryByUserNo(HttpContext.getUserNo());
        if (ToolUtil.isEmpty(user)) {
            return BaseResponse.error("用户不存在");
        } else {
            user.setPassword(pwdNew);
            saveOrUpdate(user);
            return BaseResponse.success("设置成功");
        }
    }

    public BaseResponse insertPwd(String pwdNew) {
        ShopUser user = this.queryByUserNo(HttpContext.getUserNo());
        if (ToolUtil.isNotEmpty(user.getPassword())) {
            return BaseResponse.error("您已设置过密码，不支持操作");
        } else {
            user.setPassword(pwdNew);
            saveOrUpdate(user);
            return BaseResponse.success("设置成功");
        }
    }

    /**
     * 用户购买商品是绑定业绩到上级
     *
     * @return
     */
    public String queryParentUserNo(String userNo, Integer vipLevel) {
        ShopUser user = queryByUserNo(userNo);
        if (ToolUtil.isNotEmpty(user) && ToolUtil.isNotEmpty(user.getParentUserNo())) {
            String parentUserNo = user.getParentUserNo();
            while (true) {
                ShopUser parentUser = queryByUserNo(parentUserNo);
                if (ToolUtil.isEmpty(parentUser)) {
                    return userNo;
                }
                if (vipLevel.equals(0)) {
                    return userNo;
                } else if (vipLevel.equals(1)) {
                    if (parentUser.getVipLevel() >= 1) {
                        if (parentUser.getUserNo().equals("US0001")) {
                            return userNo;
                        }
                        return parentUser.getUserNo();
                    }
                } else if (vipLevel > 1) {
                    if (parentUser.getVipLevel() > 1) {
                        if (parentUser.getUserNo().equals("US0001")) {
                            return userNo;
                        }
                        return parentUser.getUserNo();
                    }
                }
                parentUserNo = parentUser.getParentUserNo();
            }
        }
        return "";
    }

    /**
     * 校验当前用户 上级的LV
     *
     * @param inviteCode
     * @return
     */
    public void checkLv(String inviteCode, List<String> handleUserNos, Boolean fundUp) {
        if (ToolUtil.isEmpty(inviteCode)) {
            return;
        }
        ShopUser shopUser = queryByInviteCode(inviteCode);
        if (ToolUtil.isEmpty(shopUser)) {
            return;
        }
        String parentUserNo = shopUser.getUserNo();
        Integer lvOld = shopUser.getLv();
        handleUserNos = ToolUtil.isEmpty(handleUserNos) ? new ArrayList<>() : handleUserNos;
        List<ShopUser> shopUserList = listSubUserByParentUserNo(parentUserNo);
        List<ShopUser> sameLvShopUserList = shopUserList.stream().filter(x -> x.getLv() >= lvOld)
                .sorted(Comparator.comparingInt(ShopUser::getLv).reversed()).collect(Collectors.toList());
        if (sameLvShopUserList.size() >= 2) {
            ShopUser user1 = sameLvShopUserList.get(0);
            ShopUser user2 = sameLvShopUserList.get(1);
            Integer addLv = (user1.getLv() + user2.getLv()) / 2;
            addLv = (addLv >= (user2.getLv() + 1)) ? user2.getLv() : addLv;
            //当前账号升星
            Integer lvNew = addLv + 1;
            if (lvNew <= 5) {
                Date time = new Date();
                shopUser.setLv(lvNew);
                shopUser.setUpdateTime(time);
                if (lvNew == 2) {
                    shopUser.setInviteUpTwoTime(time);
                } else if (lvNew == 3) {
                    if (ToolUtil.isEmpty(shopUser.getInviteUpTwoTime())) {
                        shopUser.setInviteUpTwoTime(time);
                    }
                    shopUser.setInviteUpThreeTime(time);
                } else if (lvNew == 4) {
                    if (ToolUtil.isEmpty(shopUser.getInviteUpTwoTime())) {
                        shopUser.setInviteUpTwoTime(time);
                    }
                    if (ToolUtil.isEmpty(shopUser.getInviteUpThreeTime())) {
                        shopUser.setInviteUpThreeTime(time);
                    }
                    shopUser.setInviteUpFourTime(time);
                } else if (lvNew == 5) {
                    if (ToolUtil.isEmpty(shopUser.getInviteUpTwoTime())) {
                        shopUser.setInviteUpTwoTime(time);
                    }
                    if (ToolUtil.isEmpty(shopUser.getInviteUpThreeTime())) {
                        shopUser.setInviteUpThreeTime(time);
                    }
                    if (ToolUtil.isEmpty(shopUser.getInviteUpFourTime())) {
                        shopUser.setInviteUpFourTime(time);
                    }
                    shopUser.setInviteUpFiveTime(time);
                }
                this.saveOrUpdate(shopUser);
            }
            if (!lvOld.equals(lvNew)) {
                //如果有升新，则再判断该用户的上级;直到没有
                parentUserNo = shopUser.getParentUserNo();
                if (ToolUtil.isNotEmpty(parentUserNo) && !handleUserNos.contains(parentUserNo)) {
                    ShopUser parentShopUser = queryByUserNo(parentUserNo);
                    checkLv(parentShopUser.getInviteCode(), handleUserNos, null);
                }
            }
        } else {
            fundUp = ToolUtil.isNotEmpty(fundUp) ? fundUp : false;
            if (fundUp) {
                //如果是注册或者其他一些的，则判断该用户的上级;直到没有
                parentUserNo = shopUser.getParentUserNo();
                if (ToolUtil.isNotEmpty(parentUserNo) && !handleUserNos.contains(parentUserNo)) {
                    ShopUser parentShopUser = queryByUserNo(parentUserNo);
                    checkLv(parentShopUser.getInviteCode(), handleUserNos, null);
                }
            }
        }
    }

    public Integer teamCount(String userNo) {
        ShopUser user = queryByUserNo(userNo);
        String subUserIds = user.getSubUserId();
        List<String> all = Arrays.asList(subUserIds.split(","));
        List<String> subUserIdList = all.stream().filter(x -> ToolUtil.isNotEmpty(x)).distinct().collect(Collectors.toList());
        user.setSubUserId(EntityConvertUtils.listToString(subUserIdList));
        this.saveOrUpdate(user);
        return subUserIdList.size() + 1;
    }

    private List<ShopUser> listSubUserByParentUserNo(String parentUserNo) {
        LambdaQueryWrapper<ShopUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShopUser::getParentUserNo, parentUserNo);
        return list(queryWrapper);
    }

    public synchronized BaseResponse setParentUser(String inviteCode) {
        ShopUser shopUser = this.queryByUserNo(HttpContext.getUserNo());
        if (ToolUtil.isNotEmpty(shopUser.getParentUserNo())) {
            return BaseResponse.error("用户已经绑定过上级");
        }
        if (inviteCode.equals(shopUser.getInviteCode())) {
            return BaseResponse.error("不能填写自己的邀请码。");
        }
        ShopUser parentUser = queryByInviteCode(inviteCode);
        if (ToolUtil.isEmpty(parentUser)) {
            return BaseResponse.error("当前邀请码未查询到用户");
        }
        if (ToolUtil.isNotEmpty(shopUser.getSubUserId())) {
            String id = parentUser.getId().toString();
            List<String> all = Arrays.asList(shopUser.getSubUserId().split(","));
            if (all.contains(id)) {
                return BaseResponse.error("不能填写自己团队中成员邀请码。");
            }
        }
        //当前账号不是会员的话不让使用
        if (parentUser.getVipLevel() < 1) {
            return BaseResponse.error("当前邀请码未激活");
        }
        shopUser.setParentUserNo(parentUser.getUserNo());
        saveOrUpdate(shopUser);
        //自己写入上级的下级
        if (!parentUser.getUserNo().equals("US0001")) {
            insertParentSubUserId(parentUser, shopUser, false);
        }
        return BaseResponse.success("成功。");
    }

    public String setParentUser1(String inviteCode, String userNo) {
        ShopUser shopUser = this.queryByUserNo(HttpContext.getUserNo());
        if (ToolUtil.isNotEmpty(userNo)) {
            shopUser = this.queryByUserNo(userNo);
        }
        if (ToolUtil.isNotEmpty(shopUser.getParentUserNo())) {
            logger.info("用户已经绑定过上级");
            return "";
        }
        if (shopUser.getInviteCode().equals(inviteCode)) {
            return "不能填写自己的邀请码。";
        }
//        if (ToolUtil.isEmpty(shopUser.getParentUserNo())) {
//            return "请填写正确的邀请码。";
//            shopUser.setParentUserNo("US0001");
//            shopUser.setInviteTime(new Date());
//            saveOrUpdate(shopUser);
//        }
//        else {
        ShopUser parentUser = queryByInviteCode(inviteCode);
        if (ToolUtil.isEmpty(parentUser)) {
            return "当前邀请码未查询到用户";
        }
        //当前账号不是会员的话不让使用
        if (parentUser.getVipLevel() < 1) {
            return "当前邀请码未激活";
        }
        shopUser.setParentUserNo(parentUser.getUserNo());
        shopUser.setInviteTime(new Date());
        saveOrUpdate(shopUser);
        //自己写入上级的下级
        if (!parentUser.getUserNo().equals("US0001")) {
            insertParentSubUserId(parentUser, shopUser, false);
        }
//        }
        return "";
    }

    public String setParentUser2(String inviteCode, String userNo) {
        ShopUser shopUser = this.queryByUserNo(HttpContext.getUserNo());
        if (ToolUtil.isNotEmpty(userNo)) {
            shopUser = this.queryByUserNo(userNo);
        }
        if (ToolUtil.isNotEmpty(shopUser.getParentUserNo())) {
            logger.info("用户已经绑定过上级");
            return "";
        }
        if (shopUser.getInviteCode().equals(inviteCode)) {
            return "不能填写自己的邀请码。";
        }
        if (ToolUtil.isEmpty(inviteCode)) {
            return "请填写正确的邀请码。";
//            shopUser.setParentUserNo("US0001");
//            shopUser.setInviteTime(new Date());
//            saveOrUpdate(shopUser);
        }
//        else {
        ShopUser parentUser = queryByInviteCode(inviteCode);
        if (ToolUtil.isEmpty(parentUser)) {
            return "当前邀请码未查询到用户";
        }
        //当前账号不是会员的话不让使用
        if (parentUser.getVipLevel() < 1) {
            return "当前邀请码未激活";
        }
        shopUser.setParentUserNo(parentUser.getUserNo());
        shopUser.setInviteTime(new Date());
        saveOrUpdate(shopUser);
        //自己写入上级的下级
        if (!parentUser.getUserNo().equals("US0001")) {
            insertParentSubUserId(parentUser, shopUser, false);
        }
//        }
        return "";
    }

    public List<ShopUser> listByNos(List<String> userNos) {
        if (ToolUtil.isEmpty(userNos)) {
            return new ArrayList<>();
        }
        LambdaQueryWrapper<ShopUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(ShopUser::getUserNo, userNos);
        return this.list(queryWrapper);
    }

    public List<ShopUser> listByPhones(List<String> phones) {
        if (ToolUtil.isEmpty(phones)) {
            return new ArrayList<>();
        }
        LambdaQueryWrapper<ShopUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(ShopUser::getPhone, phones);
        return this.list(queryWrapper);
    }

//    public BaseResponse userList() {
//        return BaseResponse.success();
//    }

    public BaseResponse<List<GopShopUserListResult>> gopShopUserList(GopQueryUserListParams param) {
        Page pageContext = BasePageFactory.defaultPage(param.getPage(), param.getLimit());
        LambdaQueryWrapper<ShopUser> queryWrapper = new LambdaQueryWrapper<>();
        if (ToolUtil.isNotEmpty(param.getLv())) {
            queryWrapper.eq(ShopUser::getLv, param.getLv());
        }
        if (ToolUtil.isNotEmpty(param.getVipLevel())) {
            queryWrapper.eq(ShopUser::getVipLevel, param.getVipLevel());
        }
        if (ToolUtil.isNotEmpty(param.getIsSubCompany())) {
            if (param.getIsSubCompany().equals("1")) {
                queryWrapper.ne(ShopUser::getSubCompany, "");
            } else if (param.getIsSubCompany().equals("2")) {
                queryWrapper.eq(ShopUser::getSubCompany, "");
            }
        }
        if (ToolUtil.isNotEmpty(param.getPhone())) {
            queryWrapper.eq(ShopUser::getPhone, param.getPhone());
        }
        if (ToolUtil.isNotEmpty(param.getName())) {
            queryWrapper.like(ShopUser::getNickName, param.getName());
        }
        if (ToolUtil.isNotEmpty(param.getInviteCode())) {
            queryWrapper.like(ShopUser::getInviteCode, param.getInviteCode());
        }
        if (!ToolUtil.isAllEmpty(param.getStartTime(), param.getEndTime())) {
            queryWrapper.and(x -> x.ge(ShopUser::getCreateTime, DateUtils.getDateStart(param.getStartTime()))
                    .le(ShopUser::getCreateTime, DateUtils.getDateEnd(param.getEndTime())));
        }
        queryWrapper.ne(ShopUser::getPhone, "");
        queryWrapper.eq(ShopUser::getIsDeleted, false);
//        queryWrapper.orderByDesc(ShopUser::getCreateTime);
        queryWrapper.orderByDesc(ShopUser::getLv);
        IPage page = this.page(pageContext, queryWrapper);
        List<ShopGoods> shopGoodsList = page.getRecords();
        List<GopShopUserListResult> list = EntityConvertUtils.convertAListToBList(shopGoodsList, GopShopUserListResult.class);
        for (GopShopUserListResult result : list) {
            String userNo = result.getUserNo();
            result.setUserBalance(userAccountService.getUserMoneyAccountNowBalance(userNo)
                    .setScale(2, BigDecimal.ROUND_HALF_UP).toString());
            result.setUserPoint(shopOrderPointsService.getTotalPoint(userNo, null).toString());
            UserLogInfo logInfo = userLogInfoService.queryLastLoginByUserNo(result.getUserNo());
            if (ToolUtil.isNotEmpty(logInfo)) {
                result.setLastLoginTime(logInfo.getLogTime());
            }
        }
        page.setRecords(list);
        return BasePageFactory.createPageInfo(page);
    }

    public BaseResponse<GopShopUserDetailResult> gopShopUserDetail(String userNo) {
        LambdaQueryWrapper<ShopUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShopUser::getIsDeleted, false);
        queryWrapper.eq(ShopUser::getUserNo, userNo);
        ShopUser user = this.getOne(queryWrapper);
        if (ToolUtil.isNotEmpty(user)) {
            GopShopUserDetailResult result = EntityConvertUtils.convertAToB(user, GopShopUserDetailResult.class);
            result.setUserBalance(userAccountService.getUserMoneyAccountNowBalance(userNo)
                    .setScale(2, BigDecimal.ROUND_HALF_UP).toString());
            result.setUserPoint(shopOrderPointsService.getTotalPoint(userNo, null).toString());
            UserLogInfo logInfo = userLogInfoService.queryLastLoginByUserNo(userNo);
            if (ToolUtil.isNotEmpty(logInfo)) {
                result.setLastLoginTime(logInfo.getLogTime());
            }
            List<ShopUser> shopUserList = this.listSubUserByParentUserNo(result.getUserNo());
            shopUserList = shopUserList.stream().filter(x -> x.getLv().equals(5)).collect(Collectors.toList());
            result.setLvFiveCount(shopUserList.size());
            //当月拉新人数
            result.setMonthCount(getInvtieMonthCount(userNo));
            return BaseResponse.success(result);
        }
        return BaseResponse.error("用户不存在");
    }

    private Integer getInvtieMonthCount(String userNo) {
        LambdaQueryWrapper<ShopUser> queryWrappe = new LambdaQueryWrapper<>();
        queryWrappe.isNotNull(ShopUser::getInviteTime);
        Date startTime = DateUtils.getMonthStart(DateUtils.format(new Date()));
        Date endTime = DateUtils.getMonthEnd(DateUtils.format(new Date()));
        queryWrappe.eq(ShopUser::getParentUserNo, userNo);
        queryWrappe.ge(ShopUser::getInviteTime, startTime);
        queryWrappe.le(ShopUser::getInviteTime, endTime);
        return list(queryWrappe).size();
    }

    public BaseResponse<List<GopShopUserInviteUserResult>> gopShopUserInviteUser(GopShopUserInviteUserParams param) {
        Page pageContext = BasePageFactory.defaultPage(param.getPage(), param.getLimit());
        LambdaQueryWrapper<ShopUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShopUser::getParentUserNo, param.getUserNo());
        if (ToolUtil.isNotEmpty(param.getPhone())) {
            queryWrapper.like(ShopUser::getPhone, param.getPhone());
        }
        if (!ToolUtil.isAllEmpty(param.getStartTime(), param.getEndTime())) {
            queryWrapper.and(x -> x.ge(ShopUser::getInviteTime, DateUtils.getDateStart(param.getStartTime()))
                    .le(ShopUser::getInviteTime, DateUtils.getDateEnd(param.getEndTime())));
        }
        if (ToolUtil.isNotEmpty(param.getLv())) {
            queryWrapper.eq(ShopUser::getLv, Integer.parseInt(param.getLv()));
        }
        queryWrapper.orderByDesc(ShopUser::getLv);
        queryWrapper.orderByAsc(ShopUser::getCreateTime);
        IPage page = this.page(pageContext, queryWrapper);
        List<ShopUser> shopUserList = page.getRecords();
        List<GopShopUserInviteUserResult> list =
                EntityConvertUtils.convertAListToBList(shopUserList, GopShopUserInviteUserResult.class);
        for (GopShopUserInviteUserResult result : list) {
            LambdaQueryWrapper<ShopUser> queryWrapper2 = new LambdaQueryWrapper<>();
            queryWrapper2.eq(ShopUser::getParentUserNo, result.getUserNo());
            result.setSubUserCount(list(queryWrapper2).size());
        }
        page.setRecords(list);
        return BasePageFactory.createPageInfo(page);
    }

    public BaseResponse<List<GopShopUserTeamBuySpecialGoodsResult>> shopUserTeamBuySpecialGoodsList(TeamBuySpecialGoodsParams params) {
        Date startDay;
        Date endDay;
        if (ToolUtil.isAllEmpty(params.getStartTime(), params.getEndTime())) {
            startDay = DateUtils.getDateStart(DateUtils.addDay(-1));
            endDay = DateUtils.getDateEnd(DateUtils.addDay(-1));
        } else {
            startDay = DateUtils.getDateStart(params.getStartTime());
            endDay = DateUtils.getDateEnd(params.getEndTime());
        }
        List<GopShopUserTeamBuySpecialGoodsResult> list = new ArrayList<>();
        String userNo = params.getUserNo();
        ShopUser user = this.queryByUserNo(userNo);
        //计算业绩
        List<ShopOrder> shopOrderListAll = shopOrderService.teamAmountByUserNo(userNo, startDay, endDay);
        //计算礼包数
        List<ShopOrder> shopOrderSpecialListAll = shopOrderService.countSpecialGoodsByUserNo(userNo, startDay, endDay);
        List<String> dailyList = DateUtils.getDayList(startDay, endDay);
        Integer size = PageWithSqlUtil.getSize(params.getPage(), params.getLimit());
        Integer index = PageWithSqlUtil.getIndex(params.getPage(), params.getLimit());
        int endPage = index + size;
        int maxListSize = dailyList.size();
        if (index > maxListSize) {
            return BaseResponse.success(new ArrayList<>());
        }
        if (endPage > maxListSize) {
            endPage = maxListSize;
        }
        List<String> dailyListPage = dailyList.subList(index, endPage);
        for (String daily : dailyListPage) {
            GopShopUserTeamBuySpecialGoodsResult result = new GopShopUserTeamBuySpecialGoodsResult();
            Date sdate = DateUtils.getDateStart(daily);
            Date edate = DateUtils.getDateEnd(daily);
            List<ShopOrder> shopOrderSpecialList = shopOrderSpecialListAll.stream().filter(x -> (x.getPayTime().getTime() <= edate.getTime()) &&
                    x.getPayTime().getTime() >= sdate.getTime()).collect(Collectors.toList());
            List<ShopOrderWhitVipLevel> shopOrderWhitVipLevelList = EntityConvertUtils.convertAListToBList(shopOrderSpecialList, ShopOrderWhitVipLevel.class);
            for (ShopOrderWhitVipLevel shopOrderWhitVipLevel : shopOrderWhitVipLevelList) {
                OrderGoodsSnapshotParam snapshotParam = JSON.parseObject(shopOrderWhitVipLevel.getSnapshot(), OrderGoodsSnapshotParam.class);
                if (ToolUtil.isEmpty(snapshotParam.getVipLevel())) {
                    shopOrderWhitVipLevel.setVipLevel(0);
                } else {
                    shopOrderWhitVipLevel.setVipLevel(snapshotParam.getVipLevel());
                }
            }
            result.setDaily(daily);
            result.setLevelOneCount(shopOrderWhitVipLevelList.stream().filter(x -> x.getVipLevel().equals(EnumVipLevel.ONE.getCode()))
                    .map(ShopOrderWhitVipLevel::getGoodsNumber).reduce(Integer::sum).orElse(0));
            result.setLevelTwoCount(shopOrderWhitVipLevelList.stream().filter(x -> x.getVipLevel().equals(EnumVipLevel.TWO.getCode()))
                    .map(ShopOrderWhitVipLevel::getGoodsNumber).reduce(Integer::sum).orElse(0));
            result.setLevelThreeCount(shopOrderWhitVipLevelList.stream().filter(x -> x.getVipLevel().equals(EnumVipLevel.THREE.getCode()))
                    .map(ShopOrderWhitVipLevel::getGoodsNumber).reduce(Integer::sum).orElse(0));
            result.setCount(shopOrderWhitVipLevelList.stream().map(ShopOrderWhitVipLevel::getGoodsNumber).reduce(Integer::sum).orElse(0));
            List<ShopOrder> shopOrderList = shopOrderListAll.stream().filter(x -> (x.getPayTime().getTime() <= edate.getTime()) &&
                    x.getPayTime().getTime() >= sdate.getTime()).collect(Collectors.toList());
            result.setAmount(shopOrderList.stream().map(ShopOrder::getPayAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
            result.setLv(getTodayLv(user, sdate));
            list.add(result);
        }
        return BaseResponse.success("返回团队礼包统计", list, dailyList.size());
    }

    /**
     * @param user 用户实体
     * @param date 今天开始时间
     * @return
     */
    private Integer getTodayLv(ShopUser user, Date date) {
        Integer lv = 1;
        if (ToolUtil.isNotEmpty(user.getInviteUpTwoTime())) {
            if (user.getInviteUpTwoTime().getTime() <= date.getTime()) {
                lv = 2;
            }
        }
        if (ToolUtil.isNotEmpty(user.getInviteUpThreeTime())) {
            if (user.getInviteUpThreeTime().getTime() <= date.getTime()) {
                lv = 3;
            }
        }
        if (ToolUtil.isNotEmpty(user.getInviteUpFourTime())) {
            if (user.getInviteUpFourTime().getTime() <= date.getTime()) {
                lv = 4;
            }
        }
        if (ToolUtil.isNotEmpty(user.getInviteUpFiveTime())) {
            if (user.getInviteUpFiveTime().getTime() <= date.getTime()) {
                lv = 5;
            }
        }
        return lv;
    }

    /**
     * 用户的id集合转变成UserNo集合
     *
     * @param ids
     * @return
     */
    public List<String> entityConvertIds2Nos(String ids) {
        List<String> idStrList = Arrays.asList(ids.split(","));
        List<String> subIdStrList = idStrList.stream().filter(x -> ToolUtil.isNotEmpty(x)).distinct().collect(Collectors.toList());
        if (ToolUtil.isEmpty(subIdStrList)) {
            return new ArrayList<>();
        }
        List<Long> idLongList = subIdStrList.stream().map(i -> Long.parseLong(i)).collect(Collectors.toList());
        LambdaQueryWrapper<ShopUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(ShopUser::getId, idLongList);
        List<ShopUser> shopUserList = list(queryWrapper);
        return shopUserList.stream().map(ShopUser::getUserNo).collect(Collectors.toList());
    }

    /**
     * 设置成会员账号
     *
     * @param userNo
     */
    public void setVipUser(String userNo, String snapshot) {
        OrderGoodsSnapshotParam snapshotParam = JSON.parseObject(snapshot, OrderGoodsSnapshotParam.class);
        Integer vipLevel = snapshotParam.getVipLevel();
        ShopUser shopUser = queryByUserNo(userNo);
        if (vipLevel > shopUser.getVipLevel()) {
            shopUser.setVipLevel(vipLevel);
            shopUser.setUpdateTime(new Date());
            this.saveOrUpdate(shopUser);
        }
        return;
    }

    public BaseResponse<SeeParentUserResult> seeParentUser() {
        String userNo = HttpContext.getUserNo();
        ShopUser shopUser = this.queryByUserNo(userNo);
        if (ToolUtil.isEmpty(shopUser) || ToolUtil.isEmpty(shopUser.getParentUserNo())) {
            return BaseResponse.error("当前无推荐人。");
        }
        SeeParentUserResult parentShopUser =
                EntityConvertUtils.convertAToB(this.queryByUserNo(shopUser.getParentUserNo()), SeeParentUserResult.class);
        parentShopUser.setPhone(parentShopUser.getPhone().replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2"));
        return BaseResponse.success(parentShopUser);
    }


    /**
     * 微信登录，比对unionId/openid，如果为空则创新用户
     *
     * @param param 微信登录参数
     * @return 微信在平台的用户
     */
    public ShopUser loginWeChat(AppUserWXParam param) {
        logger.info(JSON.toJSONString(param) + "-------AppUserWXParam!-------");
        LambdaQueryWrapper<ShopUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShopUser::getIsDeleted, false);
        if (ToolUtil.isNotEmpty(param.getWxOpenId())) {
            queryWrapper.and(x -> x.eq(ShopUser::getWxUnionId, param.getUnionId()).eq(ShopUser::getWxOpenId, param.getWxOpenId()));
//        } else if (ToolUtil.isNotEmpty(param.getWxH5OpenId())) {
//            queryWrapper.and(x -> x.eq(ShopUser::getWxUnionId, param.getUnionId()).eq(ShopUser::getWxJsOpenId, param.getWxH5OpenId()));
        } else if (ToolUtil.isNotEmpty(param.getWxMiniOpenId())) {
            queryWrapper.and(x -> x.eq(ShopUser::getWxUnionId, param.getUnionId()).eq(ShopUser::getWxMiniOpenId, param.getWxMiniOpenId()));
        } else if (ToolUtil.isNotEmpty(param.getWxJsOpenId())) {
            queryWrapper.and(x -> x.eq(ShopUser::getWxUnionId, param.getUnionId()).eq(ShopUser::getWxJsOpenId, param.getWxJsOpenId()));
        }
        queryWrapper.last("limit 1");
        ShopUser user = this.getOne(queryWrapper);
        if (ToolUtil.isEmpty(user)) {
            Date time = new Date();
            //通过unionId判断是否在其他端登录过
            queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ShopUser::getIsDeleted, false);
            queryWrapper.eq(ShopUser::getWxUnionId, param.getUnionId());
            queryWrapper.last("limit 1");
            user = this.getOne(queryWrapper);
            if (ToolUtil.isEmpty(user)) {
                //add生成用户 返回token直接登录
                String userNo = RedisUtil.getServiceKeyHaveDateByType(ServiceKeyTypeEnum.USER.getValue());
                String inviteCode = getNewTgm();

                user = ShopUser.builder().userNo(userNo).nickName(param.getWxName()).phone("")
                        .avatar(param.getWxAvatar()).sex(EnumGenderType.UN_KNOW.getCode()).inviteCode(inviteCode).subUserId("").lv(1).parentUserNo("")
                        .wxNickName(param.getWxName()).wxAvatar(param.getWxAvatar()).wxOpenId(param.getWxMiniOpenId()).wxMiniOpenId(param.getWxMiniOpenId())
                        .trueName("").identityCard("").wxJsOpenId(param.getWxJsOpenId()).wxUnionId(param.getUnionId())
                        .isDeleted(false).isInvalid(false).createTime(time)
                        .build();
                this.save(user);
                //生成二维码头像
                ImageUtil.greatQRCodeImg(ShopUserService.getContent(user.getNickName(), user.getUserNo(), user.getInviteCode())
                        , user.getInviteCode(), user.getAvatar(), EnumQRCodeType.ONE.getCode());
            } else {
                //通过不同路径进入账号绑定之前授权过的账号
                if (ToolUtil.isNotEmpty(param.getWxOpenId())) {
                    user.setWxOpenId(param.getWxOpenId());
                }
//                if (ToolUtil.isNotEmpty(param.getWxH5OpenId())) {
//                    user.setWxH5OpenId(param.getWxH5OpenId());
//                }
                if (ToolUtil.isNotEmpty(param.getWxMiniOpenId())) {
                    user.setWxMiniOpenId(param.getWxMiniOpenId());
                }
                if (ToolUtil.isNotEmpty(param.getWxJsOpenId())) {
                    user.setWxJsOpenId(param.getWxJsOpenId());
                }
                user.setWxAvatar(param.getWxAvatar());
                this.saveOrUpdate(user);
            }
            return user;
        } else {
            if (user.getIsInvalid()) {
                logger.warn("对应账号已限制绑定" + JSON.toJSONString(param));
                return null;
            } else {
                if (!user.getWxAvatar().equals(param.getWxAvatar())) {
                    //可能涉及到替换头像
                    user.setWxAvatar(param.getWxAvatar());
                    this.saveOrUpdate(user);
                }
                return user;
            }
        }
    }

    public BaseResponse removeAccount() {
        String userNo = HttpContext.getUserNo();
        //修改用户是否注销状态
        ShopUser user = this.queryByUserNo(userNo);
        logger.info("当前账号用户自行注销【留档】：" + JSONObject.toJSONString(user));
        user.setUpdateTime(new Date());
        //同时删除授权信息
        user.setWxUnionId("");
        user.setWxOpenId("");
        user.setWxJsOpenId("");
        user.setWxMiniOpenId("");
        user.setWxAvatar("");
        user.setWxNickName("");
        user.setIsDeleted(true);
        user.setPhone("10000000000");
        this.saveOrUpdate(user);
        return BaseResponse.success("账号注销成功！");
    }

    public BaseResponse bingPhone(String phone, String code, Integer type) {
        ShopUser thisUser = this.queryByUserNo(HttpContext.getUserNo());
        ShopUser phoneUser = queryTrueUserByPhone(phone);
        if (ToolUtil.isNotEmpty(thisUser) && ToolUtil.isNotEmpty(thisUser.getPhone())) {
            return BaseResponse.error("该账号已绑定了手机");
        }
        //校验新手机短信密码
        if (!verificationCodeService.checkCode(phone, EnumVerificationType.BING_PHONE.getCode(), code)) {
            return BaseResponse.error("验证码校验失败");
        }
        if (ToolUtil.isEmpty(thisUser)) {
            throw new NoMsgException(302, "系统异常302");
        }
        //判断当前phone 账号是否有对应的关系所绑定
        UserSimple userSimple;
        if (type.equals(EnumDecodeType.WECHAT.getCode())) {
            if (ToolUtil.isEmpty(phoneUser)) {
                phoneUser = EntityConvertUtils.convertAToB(thisUser, ShopUser.class);
                phoneUser.setId(null);
                phoneUser.setUserNo(RedisUtil.getServiceKeyHaveDateByType(ServiceKeyTypeEnum.USER.getValue()));
                phoneUser.setPhone(phone);
            } else {
                if (ToolUtil.isNotEmpty(phoneUser.getWxUnionId()) && !phoneUser.getWxUnionId().equals(thisUser.getWxUnionId())) {
                    return BaseResponse.error("当前手机号已授权绑定过其他微信");
                }
            }
            phoneUser.setWxNickName(thisUser.getWxNickName());
            phoneUser.setWxAvatar(thisUser.getWxAvatar());
            phoneUser.setWxOpenId(thisUser.getWxOpenId());
            phoneUser.setWxJsOpenId(thisUser.getWxJsOpenId());
            phoneUser.setWxMiniOpenId(thisUser.getWxMiniOpenId());
            phoneUser.setWxUnionId(thisUser.getWxUnionId());
            this.saveOrUpdate(phoneUser);
            this.removeById(thisUser.getId());
        } else if (type.equals(EnumDecodeType.APPLE.getCode())) {
            if (ToolUtil.isEmpty(phoneUser)) {
                phoneUser = EntityConvertUtils.convertAToB(thisUser, ShopUser.class);
                phoneUser.setId(null);
                phoneUser.setUserNo(RedisUtil.getServiceKeyHaveDateByType(ServiceKeyTypeEnum.USER.getValue()));
                phoneUser.setPhone(phone);
            } else {
                if (ToolUtil.isNotEmpty(phoneUser.getAppleSub())) {
                    return BaseResponse.error("当前手机号已授权绑定过苹果账号");
                }
            }
            phoneUser.setAppleSub(thisUser.getAppleSub());
            this.saveOrUpdate(phoneUser);
            this.removeById(thisUser.getId());
        } else {
            return BaseResponse.error("当前绑定类型错误");
        }
//        if (ToolUtil.isNotEmpty(phoneUser)) {
//            //已有用户账号 （当前用户的授权关系绑定 token返回手机账户token）
//            phoneUser.setWxNickName(user.getWxNickName());
//            phoneUser.setWxAvatar(user.getWxAvatar());
//            phoneUser.setWxMiniOpenId(user.getWxMiniOpenId());
//            phoneUser.setWxJsOpenId(user.getWxJsOpenId());
//            phoneUser.setWxUnionId(user.getWxUnionId());
//            phoneUser.setUpdateTime(new Date());
//            this.saveOrUpdate(phoneUser);
//            this.removeById(user.getId());
//            UserSimple userSimple = EntityConvertUtils.convertAToB(phoneUser, UserSimple.class);
//            token = baseService.getUserTokenHave(userSimple);
//        } else {
//            user.setPhone(phone);
//            user.setUpdateTime(new Date());
//            this.saveOrUpdate(user);
//            UserSimple userSimple = EntityConvertUtils.convertAToB(user, UserSimple.class);
//        }
        userSimple = EntityConvertUtils.convertAToB(phoneUser, UserSimple.class);
        String token = baseService.getUserTokenHave(userSimple);
        return BaseResponse.success(token);
    }

    public BaseResponse<List<MineInviteUserListResult>> mineInviteUserSupremeList() {
        Page pageContext = BasePageFactory.defaultPage("1", "6");
        String userNo = HttpContext.getUserNo();
        ShopUser shopUser = this.queryByUserNo(userNo);
        LambdaQueryWrapper<ShopUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShopUser::getParentUserNo, userNo);
        queryWrapper.eq(ShopUser::getLv, 5);
        queryWrapper.eq(ShopUser::getIsDeleted, false);
        queryWrapper.eq(ShopUser::getIsInvalid, false);
        queryWrapper.isNotNull(ShopUser::getInviteUpFourTime);
        queryWrapper.orderByAsc(ShopUser::getInviteUpFourTime);
        IPage page = this.page(pageContext, queryWrapper);
        List<MineInviteUserListResult> results = EntityConvertUtils.convertAListToBList(page.getRecords(), MineInviteUserListResult.class);
        for (MineInviteUserListResult result : results) {
            result.setPhone(EntityConvertUtils.handlePhone(result.getPhone()));
        }
        return BaseResponse.success(results);
    }

    public BaseResponse gopShopUserSetSubCompany(Long id, String subCompany, String pwd) {
        String checkPwd = dataDictionaryService.getValueStrByKey(Constant.SUB_COMPANY_PWD_KEY);
        if (ToolUtil.isEmpty(pwd) ||
                !checkPwd.equals(ToolUtil.isEmpty(pwd) ? "buDqfb12D47bf5v78ao" : pwd)) {
            return BaseResponse.error("校验密码失败");
        }
        ShopUser shopUser = this.getById(id);
        shopUser.setSubCompany(ToolUtil.isNotEmpty(subCompany) ? subCompany : "A");
        this.saveOrUpdate(shopUser);
        return BaseResponse.success("设置分公司成功");
    }

    public BaseResponse gopShopUserDeletedSubCompany(Long id, String pwd) {
        String checkPwd = dataDictionaryService.getValueStrByKey(Constant.SUB_COMPANY_PWD_KEY);
        if (ToolUtil.isEmpty(pwd) ||
                !checkPwd.equals(ToolUtil.isEmpty(pwd) ? "buDqfb12D47bf5v78ao" : pwd)) {
            return BaseResponse.error("校验密码失败");
        }
        ShopUser shopUser = this.getById(id);
        shopUser.setSubCompany("");
        this.saveOrUpdate(shopUser);
        return BaseResponse.success("取消分公司成功");
    }

//    public BaseResponse<List<GopShopUserSubCompanyInfoListResult>> gopShopUserSubCompanyInfoList(GopShopUserSubCompanyInfoListParams params) {
//        List<GopShopUserSubCompanyInfoListResult> resultList = new ArrayList<>();
//        ShopUser shopUser = queryByUserNo(params.getParentUserNo());
//        if (ToolUtil.isEmpty(shopUser) || ToolUtil.isEmpty(shopUser.getSubCompany())) {
//            return BaseResponse.success("", new ArrayList<>(), 0);
//        }
//        List<String> userNos = entityConvertIds2Nos(shopUser.getSubUserId());
//        userNos.add(shopUser.getUserNo());
//        Page pageContext = BasePageFactory.defaultPage(params.getPage(), params.getLimit());
//        LambdaQueryWrapper<ShopUser> queryWrapper = new LambdaQueryWrapper<>();
//        if (ToolUtil.isNotEmpty(params.getPhone())) {
//            queryWrapper.like(ShopUser::getPhone, params.getPhone());
//        }
//        queryWrapper.eq(ShopUser::getLv, 5);
//        queryWrapper.in(ShopUser::getUserNo, userNos);
//        IPage page = this.page(pageContext, queryWrapper);
//        List<ShopUser> shopUserList = page.getRecords();
////        List<String> userIdsList = shopUserList.stream().map(ShopUser::getSubUserId).collect(Collectors.toList());
////        String userIds = EntityConvertUtils.listToString(userIdsList);
////        List<String> userNos = entityConvertIds2Nos(userIds);
//        List<GopShopUserSubCompanyInfoListResult> list = EntityConvertUtils.convertAListToBList(shopUserList, GopShopUserSubCompanyInfoListResult.class);
//        for (GopShopUserSubCompanyInfoListResult result : list) {
//            List<String> userNoLists = entityConvertIds2Nos(result.getSubUserId());
//            userNoLists.add(shopUser.getUserNo());
//            List<ShopOrder> shopOrderList = shopOrderService.listAmountByUserNos(userNoLists, null);
//            BigDecimal amount = shopOrderList.stream().map(ShopOrder::getPayAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
//            result.setAmount(amount.setScale(2, BigDecimal.ROUND_HALF_UP).toString());
//        }
//        page.setRecords(list);
//        return BasePageFactory.createPageInfo(page);
//    }

    public BaseResponse<List<GopShopUserSubCompanyInfoListByMonthResult>> gopShopUserSubCompanyInfoList
            (GopShopUserSubCompanyInfoListParams params) {
        List<GopShopUserSubCompanyInfoListByMonthResult> resultList = new ArrayList<>();
        String userNo = params.getUserNo();
        ShopUser shopUser = queryByUserNo(userNo);
        if (ToolUtil.isEmpty(shopUser) || ToolUtil.isEmpty(shopUser.getSubCompany())) {
            return BaseResponse.error("当前非分公司账号");
        }
        List<ShopUser> shopUserListAll = listSubUserByParentUserNo(params.getUserNo());
        List<String> userNosList = this.entityConvertIds2Nos(shopUser.getSubUserId());
        List<ShopUser> subShopUserListAll = listSubUserByParentUserNos(userNosList);
        subShopUserListAll = subShopUserListAll.stream().filter(x -> x.getLv() == 5).collect(Collectors.toList());
        Date endDay;
        Date startDay;
        if (ToolUtil.isNotEmpty(params.getMonthInfo())) {
            startDay = DateUtils.getMonthStart(params.getMonthInfo());
            endDay = DateUtils.getMonthEnd(params.getMonthInfo());
        } else {
            startDay = DateUtils.getMonthStart(DateUtils.format(new Date(), DateUtils.YYYYMM));
            endDay = DateUtils.getMonthEnd(DateUtils.format(new Date(), DateUtils.YYYYMM));
        }
        //业绩
        List<ShopOrder> shopOrderListAll = shopOrderService.teamAmountByUserNo(userNo, startDay, endDay);
        String monthInfo = ToolUtil.isEmpty(params.getMonthInfo()) ? DateUtils.getMonthStartTimeStr(new Date()) : params.getMonthInfo();
        List<String> monthList = DateUtils.getMonthList(null, DateUtils.parse2Date(monthInfo, DateUtils.YYYYMM));
        for (String month : monthList) {
            //统计该月之前有多少用户是满足的。
            List<ShopUser> subShopUserList = subShopUserListAll.stream().filter(x -> ToolUtil.isNotEmpty(x.getInviteUpFiveTime())
                    && x.getInviteUpFiveTime().getTime() <= DateUtils.getMonthEnd(month).getTime()).collect(Collectors.toList());
            List<ShopUserInviteFiveCountResult> shopUserListSub = EntityConvertUtils.convertAListToBList(shopUserListAll, ShopUserInviteFiveCountResult.class);
            for (ShopUserInviteFiveCountResult fiveCountResult : shopUserListSub) {
                List<ShopUser> shopUserList = subShopUserListAll.stream().filter(x ->
                        x.getParentUserNo().equals(fiveCountResult.getUserNo())).collect(Collectors.toList());
                fiveCountResult.setList(shopUserList);
                fiveCountResult.setCount(shopUserList.size());
            }
            GopShopUserSubCompanyInfoListByMonthResult result = new GopShopUserSubCompanyInfoListByMonthResult();
            result.setMonthInfo(month);
            List<ShopOrder> shopOrderList = shopOrderListAll.stream().filter(x ->
                    x.getPayTime().getTime() >= (DateUtils.getMonthStart(month).getTime()) &&
                            x.getPayTime().getTime() <= (DateUtils.getMonthEnd(month).getTime())).collect(Collectors.toList());
            result.setAmount(shopOrderList.stream().map(ShopOrder::getPayAmount).reduce(BigDecimal.ZERO, BigDecimal::add)
                    .setScale(2, BigDecimal.ROUND_DOWN).toString());
            Integer levelOneCount = shopUserListSub.stream().filter(x -> x.getCount() >= 3 && x.getCount() <= 9).collect(Collectors.toList()).size();
            result.setPeopleLevelOne(levelOneCount);
            Integer levelTwoCount = shopUserListSub.stream().filter(x -> x.getCount() >= 10 && x.getCount() <= 29).collect(Collectors.toList()).size();
            result.setPeopleLevelTwo(levelTwoCount);
            Integer levelThreeCount = shopUserListSub.stream().filter(x -> x.getCount() >= 30).collect(Collectors.toList()).size();
            result.setPeopleLevelThree(levelThreeCount);
            resultList.add(result);
        }
        return BaseResponse.success(resultList);
    }

    private List<ShopUser> listSubUserByParentUserNos(List<String> userNosList) {
        if (ToolUtil.isEmpty(userNosList)) {
            return new ArrayList<>();
        }
        LambdaQueryWrapper<ShopUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(ShopUser::getParentUserNo, userNosList);
        return list(queryWrapper);
    }

    public BaseResponse<ShopUserSixUserListResult> gopShopUserSixUserList(String userNo, String
            startTime, String endTime) {
        ShopUser shopUser = queryByUserNo(userNo);
        LambdaQueryWrapper<ShopUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShopUser::getParentUserNo, userNo);
        queryWrapper.ge(ShopUser::getLv, EnumRatioWithLv.BLACK.getLv());
        queryWrapper.orderByAsc(ShopUser::getInviteUpFourTime);
        queryWrapper.last("limit 2,100");
        //所有满足条件的Lv4及以上，剔除前两个
        List<ShopUser> shopUserList = list(queryWrapper);
        //所有Lv5
        List<ShopUser> shopUserFiveList = shopUserList.stream().filter(x -> x.getLv().equals(EnumRatioWithLv.TOP.getLv())).collect(Collectors.toList());
        //取前4
        if (shopUserFiveList.size() >= 4) {
            shopUserFiveList = shopUserFiveList.subList(0, 4);
        }
        List<ShopUserSixUserListResult> results = EntityConvertUtils.convertAListToBList(shopUserFiveList, ShopUserSixUserListResult.class);
        Date sTime = DateUtils.getMonthStart(startTime);
        Date eTime = DateUtils.getMonthEnd(startTime);
        for (ShopUserSixUserListResult result : results) {
            if (ToolUtil.isEmpty(shopUser.getInviteUpFourTime())) {
                result.setAmount(BigDecimal.ZERO.setScale(2, BigDecimal.ROUND_HALF_UP).toString());
                continue;
            } else {
                if (sTime.getTime() <= shopUser.getInviteUpFiveTime().getTime()) {
                    sTime = shopUser.getInviteUpFiveTime();
                }
                List<ShopOrder> shopOrderList = shopOrderService.teamAmountByUserNo(userNo, sTime, eTime);
                BigDecimal amount = shopOrderList.stream().map(ShopOrder::getPayAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                result.setAmount(amount.setScale(2, BigDecimal.ROUND_HALF_UP).toString());
            }
        }
        return BaseResponse.success(results);
    }

    public BaseResponse<List<GopShopUserSubCompanyInfoUserDetailResult>> gopShopUserSubCompanyInfoDetail
            (GopShopUserSubCompanyInfoUserDetailParams params) {
        List<ShopUser> shopUserListAll = listSubUserByParentUserNo(params.getUserNo());
        List<ShopUserInviteFiveCountResult> shopUserListSub = EntityConvertUtils.convertAListToBList(shopUserListAll, ShopUserInviteFiveCountResult.class);
        List<String> userNosList = shopUserListAll.stream().map(ShopUser::getUserNo).collect(Collectors.toList());
        List<ShopUser> subShopUserListAll = listSubUserByParentUserNos(userNosList).stream().filter(x -> x.getLv() == 5).collect(Collectors.toList());
        for (ShopUserInviteFiveCountResult result : shopUserListSub) {
            List<ShopUser> shopUserList = subShopUserListAll.stream().filter(x ->
                    x.getParentUserNo().equals(result.getUserNo())).collect(Collectors.toList());
            result.setList(shopUserList);
            result.setCount(shopUserList.size());
        }
        List<ShopUserInviteFiveCountResult> fiveCountResultList = shopUserListSub;
        if (params.getType().equals(1)) {
            fiveCountResultList = shopUserListSub.stream().
                    filter(x -> x.getCount() >= 3 && x.getCount() <= 9).collect(Collectors.toList());
        } else if (params.getType().equals(2)) {
            fiveCountResultList = shopUserListSub.stream().
                    filter(x -> x.getCount() >= 10 && x.getCount() <= 29).collect(Collectors.toList());
        } else if (params.getType().equals(3)) {
            fiveCountResultList = shopUserListSub.stream().
                    filter(x -> x.getCount() >= 30).collect(Collectors.toList());
        }
        List<GopShopUserSubCompanyInfoUserDetailResult>
                gopShopUserSubCompanyInfoUserDetailResultList = EntityConvertUtils.convertAListToBList(
                fiveCountResultList, GopShopUserSubCompanyInfoUserDetailResult.class);
        return BaseResponse.success(gopShopUserSubCompanyInfoUserDetailResultList);
    }

    public BaseResponse<List<GopShopUserSubCompanyInfoListByMonthResult>> gopShopUserSubCompanyInfoListPeo
            (GopShopUserSubCompanyInfoListParams params) {
        //时间
        Date startDay;
        Date endDay;
        if (ToolUtil.isEmpty(params.getMonthInfo())) {
            startDay = DateUtils.getMonthStart(DateUtils.format(new Date()));
            endDay = DateUtils.getMonthEnd(DateUtils.format(new Date()));
        } else {
            startDay = DateUtils.getMonthStart(params.getMonthInfo());
            endDay = DateUtils.getMonthEnd(params.getMonthInfo());
        }
        String monthInfo = ToolUtil.isEmpty(params.getMonthInfo()) ? DateUtils.getMonthStartTimeStr(new Date()) : params.getMonthInfo();
        //下级及下下级
        List<GopShopUserSubCompanyInfoListByMonthResult> resultList = new ArrayList<>();
        ShopUser shopUser = queryByUserNo(params.getUserNo());
        if (ToolUtil.isEmpty(shopUser)) {
            return BaseResponse.error("当前账号不存在");
        }
        List<ShopUser> shopUserListAll = listSubUserByParentUserNo(params.getUserNo());
        List<String> userNosList = shopUserListAll.stream().map(ShopUser::getUserNo).collect(Collectors.toList());
        List<ShopUser> subShopUserListAll = listSubUserByParentUserNos(userNosList).stream().filter(x -> x.getLv() == 5).collect(Collectors.toList());
//        List<ShopUser> subShopUserListAll = listSubUserByParentUserNo(params.getUserNo());
//        subShopUserListAll = subShopUserListAll.stream().filter(x -> x.getLv() == 5).collect(Collectors.toList());
        //月份列表
        List<String> monthList = DateUtils.getMonthList(null, DateUtils.parse2Date(monthInfo, DateUtils.YYYYMM));
        for (String month : monthList) {
            //统计该月之前有多少用户是满足的。
            List<ShopUser> subShopUserList = subShopUserListAll.stream().filter(x -> ToolUtil.isNotEmpty(x.getInviteUpFiveTime())
                    && x.getInviteUpFiveTime().getTime() >= DateUtils.getMonthStart(month).getTime()
                    && x.getInviteUpFiveTime().getTime() <= DateUtils.getMonthEnd(month).getTime())
                    .collect(Collectors.toList());
            List<ShopUserInviteFiveCountResult> shopUserListFirst = EntityConvertUtils.convertAListToBList(shopUserListAll, ShopUserInviteFiveCountResult.class);
            for (ShopUserInviteFiveCountResult fiveCountResult : shopUserListFirst) {
                List<ShopUser> shopUserList = subShopUserList.stream().filter(x ->
                        x.getParentUserNo().equals(fiveCountResult.getUserNo())).collect(Collectors.toList());
                fiveCountResult.setList(shopUserList);
                fiveCountResult.setCount(shopUserList.size());
            }
            GopShopUserSubCompanyInfoListByMonthResult result = new GopShopUserSubCompanyInfoListByMonthResult();
            result.setMonthInfo(month);
            Integer levelOneCount = shopUserListFirst.stream().filter(x -> x.getCount() >= 3 && x.getCount() <= 9).collect(Collectors.toList()).size();
            result.setPeopleLevelOne(levelOneCount);
            Integer levelTwoCount = shopUserListFirst.stream().filter(x -> x.getCount() >= 10 && x.getCount() <= 29).collect(Collectors.toList()).size();
            result.setPeopleLevelTwo(levelTwoCount);
            Integer levelThreeCount = shopUserListFirst.stream().filter(x -> x.getCount() >= 30).collect(Collectors.toList()).size();
            result.setPeopleLevelThree(levelThreeCount);
            resultList.add(result);
        }
        return BaseResponse.success(resultList);
    }

    public BaseResponse<List<GopShopUserSubCompanyInfoUserDetailResult>> gopShopUserSubCompanyInfoDetailPeo
            (GopShopUserSubCompanyInfoUserDetailParams params) {
        List<ShopUser> shopUserListAll = listSubUserByParentUserNo(params.getUserNo());
        List<ShopUserInviteFiveCountResult> shopUserListSub = EntityConvertUtils.convertAListToBList(shopUserListAll, ShopUserInviteFiveCountResult.class);
        List<String> userNosList = shopUserListAll.stream().map(ShopUser::getUserNo).collect(Collectors.toList());
        List<ShopUser> subShopUserListAll = listSubUserByParentUserNos(userNosList).stream().filter(x -> x.getLv() == 5).collect(Collectors.toList());
        subShopUserListAll = subShopUserListAll.stream().filter(x -> ToolUtil.isNotEmpty(x.getInviteUpFiveTime())
                && x.getInviteUpFiveTime().getTime() >= DateUtils.getMonthStart(params.getMonthInfo()).getTime()
                && x.getInviteUpFiveTime().getTime() <= DateUtils.getMonthEnd(params.getMonthInfo()).getTime()).collect(Collectors.toList());
        for (ShopUserInviteFiveCountResult result : shopUserListSub) {
            List<ShopUser> shopUserList = subShopUserListAll.stream().filter(x ->
                    x.getParentUserNo().equals(result.getUserNo())).collect(Collectors.toList());
            result.setList(shopUserList);
            result.setCount(shopUserList.size());
        }
        List<ShopUserInviteFiveCountResult> fiveCountResultList = shopUserListSub;
        if (params.getType().equals(1)) {
            fiveCountResultList = shopUserListSub.stream().
                    filter(x -> x.getCount() >= 3 && x.getCount() <= 9).collect(Collectors.toList());
        } else if (params.getType().equals(2)) {
            fiveCountResultList = shopUserListSub.stream().
                    filter(x -> x.getCount() >= 10 && x.getCount() <= 29).collect(Collectors.toList());
        } else if (params.getType().equals(3)) {
            fiveCountResultList = shopUserListSub.stream().
                    filter(x -> x.getCount() >= 30).collect(Collectors.toList());
        }
        List<GopShopUserSubCompanyInfoUserDetailResult>
                gopShopUserSubCompanyInfoUserDetailResultList = EntityConvertUtils.convertAListToBList(
                fiveCountResultList, GopShopUserSubCompanyInfoUserDetailResult.class);
        return BaseResponse.success(gopShopUserSubCompanyInfoUserDetailResultList);
    }

    public ShopUser appleLogin(UserInfoApple param) {
        logger.info(JSON.toJSONString(param) + "-------AppUserAppleParam!-------");
        LambdaQueryWrapper<ShopUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShopUser::getIsDeleted, false);
        if (ToolUtil.isNotEmpty(param.getSub())) {
            queryWrapper.eq(ShopUser::getAppleSub, param.getSub());
        }
        queryWrapper.last("limit 1");
        ShopUser user = this.getOne(queryWrapper);
        if (ToolUtil.isEmpty(user)) {
            //暂时不处理unionId问题
            //add生成用户 返回token直接登录
            String userNo = RedisUtil.getServiceKeyHaveDateByType(ServiceKeyTypeEnum.USER.getValue());
            String inviteCode = getNewTgm();
            String avatar = Constant.getDefaultAvatar();
            String name = "Apple用户" + inviteCode;
            Date time = new Date();
            user = ShopUser.builder().userNo(userNo).nickName(name).phone("")
                    .avatar(avatar).sex(EnumGenderType.UN_KNOW.getCode()).inviteCode(inviteCode)
                    .subUserId("").lv(1).parentUserNo("")
                    .wxNickName("").wxAvatar("").wxOpenId("").wxMiniOpenId("")
                    .trueName("").identityCard("").wxJsOpenId("").wxUnionId("")
                    .appleSub(param.getSub()).isDeleted(false).isInvalid(false).createTime(time)
                    .build();
            this.save(user);
            //生成二维码头像
            ImageUtil.greatQRCodeImg(ShopUserService.getContent(user.getNickName(), user.getUserNo(), user.getInviteCode())
                    , user.getInviteCode(), user.getAvatar(), EnumQRCodeType.ONE.getCode());
            return user;
        } else {
            if (user.getIsInvalid()) {
                return null;
            } else {
                //可能涉及到替换头像
                return user;
            }
        }
    }

    /**
     * 绑定微信
     *
     * @param type
     * @param code
     * @return
     */
    public BaseResponse<Boolean> bindingWeChat(Integer type, String code) {
        WeChatDecodeUserResult weChatDecodeUserResult = wxDecodeService.getUserInfo(type, code);
        if (ToolUtil.isEmpty(weChatDecodeUserResult)) {
            return BaseResponse.error("微信授权服务出错！");
        }
        String userNo = HttpContext.getUserNo();
        String openId = type.equals(EnumDecodeClientType.CLIENT.getCode()) ? weChatDecodeUserResult.getOpenid() : "";
        String h5OpenId = type.equals(EnumDecodeClientType.H5.getCode()) ? weChatDecodeUserResult.getOpenid() : "";
        String miniOpenId = type.equals(EnumDecodeClientType.MINI.getCode()) ? weChatDecodeUserResult.getOpenid() : "";
        String jsOpenId = type.equals(EnumDecodeClientType.JS.getCode()) ? weChatDecodeUserResult.getOpenid() : "";
        String unionId = weChatDecodeUserResult.getUnionid();
        String headImgUrl = weChatDecodeUserResult.getHeadimgurl();
        String nickName = weChatDecodeUserResult.getNickname();
        Integer gender = weChatDecodeUserResult.getSex();
        LambdaQueryWrapper<ShopUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShopUser::getIsDeleted, false);
        queryWrapper.eq(ShopUser::getWxUnionId, unionId);
        queryWrapper.last("limit 1");
        //微信对应账号【可能是已经有完全数据的账号】
        ShopUser wxUser = this.getOne(queryWrapper);
        //登录对应账号【肯定是没有绑定微信的，也可能没有手机号】
        ShopUser appUser = this.queryByUserNo(userNo);
        //如果当前查询到的账号是没有绑定手机号的，则当前登录用户直接绑定，否则提示不能同意绑定
        if (ToolUtil.isNotEmpty(wxUser)) {
            if (ToolUtil.isNotEmpty(wxUser.getPhone())) {
                //手机账户 + 未绑定微信
                if (ToolUtil.isNotEmpty(appUser.getPhone())) {
                    //微信对应手机号不是本手机号
                    if (!wxUser.getPhone().equals(appUser.getPhone())) {
                        return BaseResponse.error("当前微信已经绑定了其他账号", false);
                    } else {
                        //可以绑定
                        if (ToolUtil.isNotEmpty(openId)) {
                            wxUser.setWxOpenId(openId);
                        }
                        if (ToolUtil.isNotEmpty(miniOpenId)) {
                            wxUser.setWxMiniOpenId(miniOpenId);
                        }
                        if (ToolUtil.isNotEmpty(h5OpenId)) {
                            wxUser.setWxJsOpenId(h5OpenId);
                        }
                        if (ToolUtil.isNotEmpty(jsOpenId)) {
                            wxUser.setWxJsOpenId(jsOpenId);
                        }
                        wxUser.setWxAvatar(headImgUrl);
                        wxUser.setWxNickName(nickName);
                        wxUser.setSex(gender);
                        wxUser.setUpdateTime(new Date());
                        return BaseResponse.success("通信成功", this.saveOrUpdate(wxUser) ? true : false);
                    }
                }
                // 没有手机号的微信授权账号[不会出现]
                return BaseResponse.error("系统异常，请联系客服", false);
            } else {
                //微信账号未绑定手机号，则删除微信账号，绑定覆盖到登录账号
                this.removeById(wxUser.getId());
                if (ToolUtil.isNotEmpty(h5OpenId)) {
                    appUser.setWxJsOpenId(h5OpenId);
                }
                if (ToolUtil.isNotEmpty(miniOpenId)) {
                    appUser.setWxMiniOpenId(miniOpenId);
                }
                if (ToolUtil.isNotEmpty(h5OpenId)) {
                    appUser.setWxJsOpenId(h5OpenId);
                }
                if (ToolUtil.isNotEmpty(jsOpenId)) {
                    appUser.setWxJsOpenId(jsOpenId);
                }
                appUser.setWxAvatar(headImgUrl);
                appUser.setWxNickName(nickName);
                appUser.setSex(gender);
                appUser.setUpdateTime(new Date());
                return BaseResponse.success("通信成功(绑定微信成功)", this.saveOrUpdate(appUser) ? true : false);
            }
        } else {
            this.removeById(wxUser.getId());
            appUser.setWxUnionId(unionId);
            appUser.setWxJsOpenId(h5OpenId);
            appUser.setWxMiniOpenId(miniOpenId);
            appUser.setWxJsOpenId(jsOpenId);
            appUser.setWxAvatar(headImgUrl);
            appUser.setWxNickName(nickName);
            appUser.setSex(gender);
            appUser.setUpdateTime(new Date());
            return BaseResponse.success("通信成功（直接首绑微信成功）", this.saveOrUpdate(appUser) ? true : false);
        }
    }

    public BaseResponse<AppTeamAmountResult> teamAmount() {
        AppTeamAmountResult result = new AppTeamAmountResult();
        String userNo = HttpContext.getUserNo();
        List<ShopOrder> shopOrderListAll = shopOrderService.teamAmountByUserNo(userNo, null, null);
        List<HalfDateInfoResult> halfDateInfoResultList =
                DateUtils.getHalfOfTheMonthInfo(DateUtils.getMonthStart("2022-03"));
        List<HalfDateInfoWithAmountResult> list = EntityConvertUtils.convertAListToBList(
                halfDateInfoResultList, HalfDateInfoWithAmountResult.class);
        for (HalfDateInfoWithAmountResult result1 : list) {
            result1.setHalfDayInfoNameAmountStr(result1.getHalfDayInfoName() + "业绩：");
            List<ShopOrder> halfShopOrderList = shopOrderListAll.stream().filter(x ->
                    x.getPayTime().getTime() <= result1.getEdate().getTime() &&
                            x.getPayTime().getTime() >= result1.getSdate().getTime()).collect(Collectors.toList());
            result1.setAmount(halfShopOrderList.stream().map(ShopOrder::getPayAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, BigDecimal.ROUND_DOWN));
        }
        result.setList(list);
        result.setTotalAmount(shopOrderListAll.stream().map(ShopOrder::getPayAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, BigDecimal.ROUND_DOWN));
        Date today = new Date();
        List<ShopOrder> todayShopOrderList = shopOrderListAll.stream().filter(x ->
                x.getPayTime().getTime() <= DateUtils.getDateEnd(today).getTime() &&
                        x.getPayTime().getTime() >= DateUtils.getDateStart(today).getTime()).collect(Collectors.toList());
        result.setTodayAmount(todayShopOrderList.stream().map(ShopOrder::getPayAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, BigDecimal.ROUND_DOWN));
        return BaseResponse.success(result);
    }


    /**
     * 获取用户的上下级
     * @param phone
     * @return
     */
    public List<String> getUserList(String phone){
        List<String> list = this.baseMapper.getUserPhoneList(phone);
        String parentUserPhone = this.baseMapper.getParentUserPhoneList(phone);
        if(ToolUtil.isNotEmpty(parentUserPhone)){
            list.add(parentUserPhone);
        }
        return  list;
    }
}
